<?php
// +----------------------------------------------------------------------
// | OneThink [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2013 http://www.onethink.cn All rights reserved.
// +----------------------------------------------------------------------
// | Author: 麦当苗儿 <zuojiazi@vip.qq.com> <http://www.zjzit.cn>
// +----------------------------------------------------------------------

define(ONETHINK_ADDON_PATH, KC_ROOT_PATH.'Addons/');

/**
 * 检测用户是否登录
 *
 * @return integer 0-未登录，大于0-当前登录用户ID
 * @author 麦当苗儿 <zuojiazi@vip.qq.com>
 */
function is_login ()
{
    $user = session('user_auth');
    return $user && session('USER_AUTH_SIGN') == data_auth_sign($user) ? $user['uid'] : 0;
}

/**
 * 检测当前用户是否为管理员
 *
 * @return boolean true-管理员，false-非管理员
 * @author 麦当苗儿 <zuojiazi@vip.qq.com>
 */
function is_administrator ($uid = null)
{
    $uid = is_null($uid) ? is_login() : $uid;
    return $uid && (intval($uid) === C('USER_ADMINISTRATOR'));
}

/**
 * 字符串转换为数组，主要用于把分隔符调整到第二个参数
 *
 * @param string $str
 *            要分割的字符串
 * @param string $glue
 *            分割符
 * @return array
 * @author 麦当苗儿 <zuojiazi@vip.qq.com>
 */
function str2arr ($str, $glue = ',')
{
    return explode($glue, $str);
}

/**
 * 数组转换为字符串，主要用于把分隔符调整到第二个参数
 *
 * @param array $arr
 *            要连接的数组
 * @param string $glue
 *            分割符
 * @return string
 * @author 麦当苗儿 <zuojiazi@vip.qq.com>
 */
function arr2str ($arr, $glue = ',')
{
    return implode($glue, $arr);
}

/**
 * 字符串截取，支持中文和其他编码
 *
 * @static
 *
 * @access public
 * @param string $str
 *            需要转换的字符串
 * @param string $start
 *            开始位置
 * @param string $length
 *            截取长度
 * @param string $charset
 *            编码格式
 * @param string $suffix
 *            截断显示字符
 * @return string
 */
function msubstr ($str, $start = 0, $length, $charset = "utf-8", $suffix = true)
{
    if (function_exists("mb_substr"))
        $slice = mb_substr($str, $start, $length, $charset);
    elseif (function_exists('iconv_substr'))
    {
        $slice = iconv_substr($str, $start, $length, $charset);
        if (false === $slice)
        {
            $slice = '';
        }
    }
    else
    {
        $re['utf-8'] = "/[\x01-\x7f]|[\xc2-\xdf][\x80-\xbf]|[\xe0-\xef][\x80-\xbf]{2}|[\xf0-\xff][\x80-\xbf]{3}/";
        $re['gb2312'] = "/[\x01-\x7f]|[\xb0-\xf7][\xa0-\xfe]/";
        $re['gbk'] = "/[\x01-\x7f]|[\x81-\xfe][\x40-\xfe]/";
        $re['big5'] = "/[\x01-\x7f]|[\x81-\xfe]([\x40-\x7e]|\xa1-\xfe])/";
        preg_match_all($re[$charset], $str, $match);
        $slice = join("", array_slice($match[0], $start, $length));
    }
    return $suffix ? $slice . '...' : $slice;
}

/**
 * 系统加密方法
 *
 * @param string $data
 *            要加密的字符串
 * @param string $key
 *            加密密钥
 * @param int $expire
 *            过期时间 单位 秒
 * @return string
 * @author 麦当苗儿 <zuojiazi@vip.qq.com>
 */
function think_encrypt ($data, $key = '', $expire = 0)
{
    $key = md5(empty($key) ? C('DATA_AUTH_KEY') : $key);
    $data = base64_encode($data);
    $x = 0;
    $len = strlen($data);
    $l = strlen($key);
    $char = '';
    
    for ($i = 0; $i < $len; $i ++)
    {
        if ($x == $l)
            $x = 0;
        $char .= substr($key, $x, 1);
        $x ++;
    }
    
    $str = sprintf('%010d', $expire ? $expire + time() : 0);
    
    for ($i = 0; $i < $len; $i ++)
    {
        $str .= chr(ord(substr($data, $i, 1)) + (ord(substr($char, $i, 1))) % 256);
    }
    return str_replace(array(
            '+',
            '/',
            '='
    ), array(
            '-',
            '_',
            ''
    ), base64_encode($str));
}

/**
 * 系统解密方法
 *
 * @param string $data
 *            要解密的字符串 （必须是think_encrypt方法加密的字符串）
 * @param string $key
 *            加密密钥
 * @return string
 * @author 麦当苗儿 <zuojiazi@vip.qq.com>
 */
function think_decrypt ($data, $key = '')
{
    $key = md5(empty($key) ? C('DATA_AUTH_KEY') : $key);
    $data = str_replace(array(
            '-',
            '_'
    ), array(
            '+',
            '/'
    ), $data);
    $mod4 = strlen($data) % 4;
    if ($mod4)
    {
        $data .= substr('====', $mod4);
    }
    $data = base64_decode($data);
    $expire = substr($data, 0, 10);
    $data = substr($data, 10);
    
    if ($expire > 0 && $expire < time())
    {
        return '';
    }
    $x = 0;
    $len = strlen($data);
    $l = strlen($key);
    $char = $str = '';
    
    for ($i = 0; $i < $len; $i ++)
    {
        if ($x == $l)
            $x = 0;
        $char .= substr($key, $x, 1);
        $x ++;
    }
    
    for ($i = 0; $i < $len; $i ++)
    {
        if (ord(substr($data, $i, 1)) < ord(substr($char, $i, 1)))
        {
            $str .= chr((ord(substr($data, $i, 1)) + 256) - ord(substr($char, $i, 1)));
        }
        else
        {
            $str .= chr(ord(substr($data, $i, 1)) - ord(substr($char, $i, 1)));
        }
    }
    return base64_decode($str);
}

function kcone_think_encrypt ($data, $key = '', $expire = 0)
{
    return 'kcone_encrypt_' . think_encrypt($data, $key, $expire);
}

function kcone_think_decrypt ($data, $key = '')
{
    if (is_string($data) && strpos($data, 'kcone_encrypt_') === 0)
    {
        $data = think_decrypt(substr($data, 14), $key);
    }
    return $data;
}

/**
 * 数据签名认证
 *
 * @param array $data
 *            被认证的数据
 * @return string 签名
 * @author 麦当苗儿 <zuojiazi@vip.qq.com>
 */
function data_auth_sign ($data)
{
    // 数据类型检测
    if (! is_array($data))
    {
        $data = (array) $data;
    }
    ksort($data); // 排序
    $code = http_build_query($data); // url编码并生成query字符串
    $sign = sha1($code); // 生成签名
    return $sign;
}

/**
 * 把返回的数据集转换成Tree
 *
 * @param array $list
 *            要转换的数据集
 * @param string $pid
 *            parent标记字段
 * @param string $level
 *            level标记字段
 * @return array
 * @author 麦当苗儿 <zuojiazi@vip.qq.com>
 */
function list_to_tree ($list, $pk = 'id', $pid = 'pid', $child = '_child', $root = 0)
{
    // 创建Tree
    $tree = array();
    if (is_array($list))
    {
        // 创建基于主键的数组引用
        $refer = array();
        foreach ($list as $key => $data)
        {
            $refer[$data[$pk]] = & $list[$key];
        }
        foreach ($list as $key => $data)
        {
            // 判断是否存在parent
            $parentId = $data[$pid];
            if ($root == $parentId)
            {
                $tree[] = & $list[$key];
            }
            else
            {
                if (isset($refer[$parentId]))
                {
                    $parent = & $refer[$parentId];
                    $parent[$child][] = & $list[$key];
                }
            }
        }
    }
    return $tree;
}

/**
 * 将list_to_tree的树还原成列表
 *
 * @param array $tree
 *            原来的树
 * @param string $child
 *            孩子节点的键
 * @param string $order
 *            排序显示的键，一般是主键 升序排列
 * @param array $list
 *            过渡用的中间数组，
 * @return array 返回排过序的列表数组
 * @author yangweijie <yangweijiester@gmail.com>
 */
function tree_to_list ($tree, $child = '_child', $order = 'id', &$list = array())
{
    if (is_array($tree))
    {
        $refer = array();
        foreach ($tree as $key => $value)
        {
            $reffer = $value;
            if (isset($reffer[$child]))
            {
                unset($reffer[$child]);
                tree_to_list($value[$child], $child, $order, $list);
            }
            $list[] = $reffer;
        }
        $list = list_sort_by($list, $order, $sortby = 'asc');
    }
    return $list;
}

/**
 * 格式化字节大小
 *
 * @param number $size
 *            字节数
 * @param string $delimiter
 *            数字和单位分隔符
 * @return string 格式化后的带单位的大小
 * @author 麦当苗儿 <zuojiazi@vip.qq.com>
 */
function format_bytes ($size, $delimiter = '')
{
    $units = array(
            'B',
            'KB',
            'MB',
            'GB',
            'TB',
            'PB'
    );
    for ($i = 0; $size >= 1024 && $i < 5; $i ++)
        $size /= 1024;
    return round($size, 2) . $delimiter . $units[$i];
}

/**
 * 设置跳转页面URL
 * 使用函数再次封装，方便以后选择不同的存储方式（目前使用cookie存储）
 *
 * @author 麦当苗儿 <zuojiazi@vip.qq.com>
 */
function set_redirect_url ($url)
{
    cookie('redirect_url', $url);
}

/**
 * 获取跳转页面URL
 *
 * @return string 跳转页URL
 * @author 麦当苗儿 <zuojiazi@vip.qq.com>
 */
function get_redirect_url ()
{
    $url = cookie('redirect_url');
    return empty($url) ? __APP__ : $url;
}

/**
 * 获取插件类的类名
 *
 * @param strng $name
 *            插件名
 */
function get_addon_class ($name)
{
    $class = "Addons\\{$name}\\{$name}Addon";
    return $class;
}

/**
 * 获取插件类的配置文件数组
 *
 * @param string $name
 *            插件名
 */
function get_addon_config ($name)
{
    $class = get_addon_class($name);
    if (class_exists($class))
    {
        $addon = new $class();
        return $addon->getConfig();
    }
    else
    {
        return array();
    }
}

/**
 * 插件显示内容里生成访问插件的url
 *
 * @param string $url
 *            url
 * @param array $param
 *            参数
 * @author 麦当苗儿 <zuojiazi@vip.qq.com>
 */
function addons_url ($url, $param = array())
{
    $url = parse_url($url);
    $case = C('URL_CASE_INSENSITIVE');
    $addons = $case ? parse_name($url['scheme']) : $url['scheme'];
    $controller = $case ? parse_name($url['host']) : $url['host'];
    $action = trim($case ? strtolower($url['path']) : $url['path'], '/');
    
    /* 解析URL带的参数 */
    if (isset($url['query']))
    {
        parse_str($url['query'], $query);
        $param = array_merge($query, $param);
    }
    
    /* 基础参数 */
    $params = array(
            '_addons' => $addons,
            '_controller' => $controller,
            '_action' => $action
    );
    $params = array_merge($params, $param); // 添加额外参数
    
    return U('Addons/execute', $params);
}

/**
 * 时间戳格式化
 *
 * @param int $time            
 * @return string 完整的时间显示
 * @author huajie <banhuajie@163.com>
 */
function time_format ($time = NULL, $format = 'Y-m-d H:i')
{
    if ($time == 0)
    {
        return "";
    }
    if ($time === null)
    {
        $time = NOW_TIME;
    }
    if (is_numeric($time))
    {
        return date($format, $time);
    }
    return $time;
}

/**
 *
 * @param $time 时间格式化
 *            兼容timestamp和时间格式
 */
function time_format_fix ($time = NULL, $format = 'Y-m-d H:i')
{
    return time_format($time, $format);
    return $time === NULL ? date($format, NOW_TIME) : (is_numeric($time) ? date($format, $time) : $time);
}

function time_format_s ($time)
{
    return date('m/d H:i:s', $time);
}

/**
 * 根据用户ID获取用户名
 *
 * @param integer $uid
 *            用户ID
 * @return string 用户名
 */
function get_username ($uid = 0)
{
    static $list;
    if (! ($uid && is_numeric($uid)))
    { // 获取当前登录用户名
        return session('user_auth.username');
    }
    
    /* 获取缓存数据 */
    if (empty($list))
    {
        $list = S('sys_active_user_list');
    }
    
    /* 查找用户信息 */
    $key = "u{$uid}";
    if (isset($list[$key]))
    { // 已缓存，直接使用
        $name = $list[$key];
    }
    else
    { // 调用接口获取用户信息
        $User = new User\Api\UserApi();
        $info = $User->info($uid);
        if ($info && isset($info[1]))
        {
            $name = $list[$key] = $info[1];
            /* 缓存用户 */
            $count = count($list);
            $max = C('USER_MAX_CACHE');
            while ($count -- > $max)
            {
                array_shift($list);
            }
            S('sys_active_user_list', $list);
        }
        else
        {
            $name = '';
        }
    }
    return $name;
}

/**
 * 根据用户ID获取用户uuid
 *
 * @return string uuid
 */
function get_useruuid ($uid = 0)
{
    $Member = D('Member');
    $map = array(
            'uid' => $uid
    );
    $uuid = $Member->field('uuid')->where($map)->find();
    return $uuid['uuid'];
}

/**
 * 根据用户ID获取用户昵称
 *
 * @param integer $uid
 *            用户ID
 * @return string 用户昵称
 */
function get_nickname ($uid = 0)
{
    static $list;
    if (! ($uid && is_numeric($uid)))
    { // 获取当前登录用户名
        return session('user_auth.username');
    }
    
    /* 获取缓存数据 */
    if (empty($list))
    {
        $list = S('sys_user_nickname_list');
    }
    
    /* 查找用户信息 */
    $key = "u{$uid}";
    if (isset($list[$key]))
    { // 已缓存，直接使用
        $name = $list[$key];
    }
    else
    { // 调用接口获取用户信息
        $info = M('Member')->field('nickname')->find($uid);
        if ($info !== false && $info['nickname'])
        {
            $nickname = $info['nickname'];
            $name = $list[$key] = $nickname;
            /* 缓存用户 */
            $count = count($list);
            $max = C('USER_MAX_CACHE');
            while ($count -- > $max)
            {
                array_shift($list);
            }
            S('sys_user_nickname_list', $list);
        }
        else
        {
            $name = '';
        }
    }
    return $name;
}

/**
 * 获取分类信息并缓存分类
 *
 * @param integer $id
 *            分类ID
 * @param string $field
 *            要获取的字段名
 * @return string 分类信息
 */
function get_category ($id, $field = null)
{
    static $list;
    
    /* 非法分类ID */
    if (empty($id) || ! is_numeric($id))
    {
        return '';
    }
    
    /* 读取缓存数据 */
    if (empty($list))
    {
        $list = S('sys_category_list');
    }
    
    /* 获取分类名称 */
    if (! isset($list[$id]))
    {
        $cate = M('Category')->find($id);
        if (! $cate || 1 != $cate['status'])
        { // 不存在分类，或分类被禁用
            return '';
        }
        $list[$id] = $cate;
        S('sys_category_list', $list); // 更新缓存
    }
    return is_null($field) ? $list[$id] : $list[$id][$field];
}

/* 根据ID获取分类标识 */
function get_category_name ($id)
{
    return get_category($id, 'name');
}

/* 根据ID获取分类名称 */
function get_category_title ($id)
{
    return get_category($id, 'title');
}

/**
 * 获取文档模型信息
 *
 * @param integer $id
 *            模型ID
 * @param string $field
 *            模型字段
 * @return array
 */
function get_document_model ($id = null, $field = null)
{
    static $list;
    
    /* 非法分类ID */
    if (! (is_numeric($id) || is_null($id)))
    {
        return '';
    }
    
    /* 读取缓存数据 */
    if (empty($list))
    {
        $list = S('DOCUMENT_MODEL_LIST');
    }
    
    /* 获取模型名称 */
    if (empty($list))
    {
        $map = array(
                'status' => 1,
                'extend' => 1
        );
        $model = M('Model')->where($map)->field(true)->select();
        foreach ($model as $value)
        {
            $list[$value['id']] = $value;
        }
        S('DOCUMENT_MODEL_LIST', $list); // 更新缓存
    }
    
    /* 根据条件返回数据 */
    if (is_null($id))
    {
        return $list;
    }
    elseif (is_null($field))
    {
        return $list[$id];
    }
    else
    {
        return $list[$id][$field];
    }
}

/**
 * 解析UBB数据
 *
 * @param string $data
 *            UBB字符串
 * @return string 解析为HTML的数据
 * @author 麦当苗儿 <zuojiazi@vip.qq.com>
 */
function ubb ($data)
{
    // TODO: 待完善，目前返回原始数据
    return $data;
}

/**
 * 记录行为日志，并执行该行为的规则
 *
 * @param string $action
 *            行为标识
 * @param string $model
 *            触发行为的模型名
 * @param int $record_id
 *            触发行为的记录id
 * @param int $user_id
 *            执行行为的用户id
 * @return boolean
 * @author huajie <banhuajie@163.com>
 */
function action_log ($action = null, $model = null, $record_id = null, $user_id = null)
{
    
    // 参数检查
    if (empty($action) || empty($model) || empty($record_id))
    {
        return '参数不能为空';
    }
    if (empty($user_id))
    {
        $user_id = is_login();
    }
    
    // 查询行为,判断是否执行
    $action_info = M('Action')->getByName($action);
    if ($action_info['status'] != 1)
    {
        return '该行为被禁用或删除';
    }
    
    // 插入行为日志
    $data['action_id'] = $action_info['id'];
    $data['user_id'] = $user_id;
    $data['action_ip'] = ip2long(get_client_ip());
    $data['model'] = $model;
    $data['record_id'] = $record_id;
    $data['create_time'] = NOW_TIME;
    
    // 解析日志规则,生成日志备注
    if (! empty($action_info['log']))
    {
        if (preg_match_all('/\[(\S+?)\]/', $action_info['log'], $match))
        {
            $log['user'] = $user_id;
            $log['record'] = $record_id;
            $log['model'] = $model;
            $log['time'] = NOW_TIME;
            $log['data'] = array(
                    'user' => $user_id,
                    'model' => $model,
                    'record' => $record_id,
                    'time' => NOW_TIME
            );
            foreach ($match[1] as $value)
            {
                $param = explode('|', $value);
                if (isset($param[1]))
                {
                    $replace[] = call_user_func($param[1], $log[$param[0]]);
                }
                else
                {
                    $replace[] = $log[$param[0]];
                }
            }
            $data['remark'] = str_replace($match[0], $replace, $action_info['log']);
        }
        else
        {
            $data['remark'] = $action_info['log'];
        }
    }
    else
    {
        // 未定义日志规则，记录操作url
        $data['remark'] = '操作url：' . $_SERVER['REQUEST_URI'];
    }
    
    M('ActionLog')->add($data);
    
    if (! empty($action_info['rule']))
    {
        // 解析行为
        $rules = parse_action($action, $user_id);
        
        // 执行行为
        $res = execute_action($rules, $action_info['id'], $user_id);
    }
}

/**
 * 解析行为规则
 * 规则定义 table:$table|field:$field|condition:$condition|rule:$rule[|cycle:$cycle|max:$max][;......]
 * 规则字段解释：table->要操作的数据表，不需要加表前缀；
 * field->要操作的字段；
 * condition->操作的条件，目前支持字符串，默认变量{$self}为执行行为的用户
 * rule->对字段进行的具体操作，目前支持四则混合运算，如：1+score*2/2-3
 * cycle->执行周期，单位（小时），表示$cycle小时内最多执行$max次
 * max->单个周期内的最大执行次数（$cycle和$max必须同时定义，否则无效）
 * 单个行为后可加 ； 连接其他规则
 *
 * @param string $action
 *            行为id或者name
 * @param int $self
 *            替换规则里的变量为执行用户的id
 * @return boolean|array: false解析出错 ， 成功返回规则数组
 * @author huajie <banhuajie@163.com>
 */
function parse_action ($action = null, $self)
{
    if (empty($action))
    {
        return false;
    }
    
    // 参数支持id或者name
    if (is_numeric($action))
    {
        $map = array(
                'id' => $action
        );
    }
    else
    {
        $map = array(
                'name' => $action
        );
    }
    
    // 查询行为信息
    $info = M('Action')->where($map)->find();
    if (! $info || $info['status'] != 1)
    {
        return false;
    }
    
    // 解析规则:table:$table|field:$field|condition:$condition|rule:$rule[|cycle:$cycle|max:$max][;......]
    $rules = $info['rule'];
    $rules = str_replace('{$self}', $self, $rules);
    $rules = explode(';', $rules);
    $return = array();
    foreach ($rules as $key => &$rule)
    {
        $rule = explode('|', $rule);
        foreach ($rule as $k => $fields)
        {
            $field = empty($fields) ? array() : explode(':', $fields);
            if (! empty($field))
            {
                $return[$key][$field[0]] = $field[1];
            }
        }
        // cycle(检查周期)和max(周期内最大执行次数)必须同时存在，否则去掉这两个条件
        if (!$return[$key] || ! array_key_exists('cycle', $return[$key]) || ! array_key_exists('max', $return[$key]))
        {
            unset($return[$key]['cycle'], $return[$key]['max']);
        }
    }
    
    return $return;
}

/**
 * 执行行为
 *
 * @param array $rules
 *            解析后的规则数组
 * @param int $action_id
 *            行为id
 * @param array $user_id
 *            执行的用户id
 * @return boolean false 失败 ， true 成功
 * @author huajie <banhuajie@163.com>
 */
function execute_action ($rules = false, $action_id = null, $user_id = null)
{
    if (! $rules || empty($action_id) || empty($user_id))
    {
        return false;
    }
    
    $return = true;
    foreach ($rules as $rule)
    {
        
        // 检查执行周期
        $map = array(
                'action_id' => $action_id,
                'user_id' => $user_id
        );
        $map['create_time'] = array(
                'gt',
                NOW_TIME - intval($rule['cycle']) * 3600
        );
        $exec_count = M('ActionLog')->where($map)->count();
        if ($exec_count > $rule['max'])
        {
            continue;
        }
        
        // 执行数据库操作
        $Model = M(ucfirst($rule['table']));
        $field = $rule['field'];
        $res = $Model->where($rule['condition'])->setField($field, array(
                'exp',
                $rule['rule']
        ));
        
        if (! $res)
        {
            $return = false;
        }
    }
    return $return;
}

// 基于数组创建目录和文件
function create_dir_or_files ($files)
{
    foreach ($files as $key => $value)
    {
        if (substr($value, - 1) == '/')
        {
            mkdir($value);
        }
        else
        {
            @file_put_contents($value, '');
        }
    }
}

if (! function_exists('array_column'))
{

    function array_column (array $input, $columnKey, $indexKey = null)
    {
        $result = array();
        if (null === $indexKey)
        {
            if (null === $columnKey)
            {
                $result = array_values($input);
            }
            else
            {
                foreach ($input as $row)
                {
                    $result[] = $row[$columnKey];
                }
            }
        }
        else
        {
            if (null === $columnKey)
            {
                foreach ($input as $row)
                {
                    $result[$row[$indexKey]] = $row;
                }
            }
            else
            {
                foreach ($input as $row)
                {
                    $result[$row[$indexKey]] = $row[$columnKey];
                }
            }
        }
        return $result;
    }
}

/**
 * 获取表名（不含表前缀）
 *
 * @param string $model_id            
 * @return string 表名
 * @author huajie <banhuajie@163.com>
 */
function get_table_name ($model_id = null)
{
    if (empty($model_id))
    {
        return false;
    }
    $Model = M('Model');
    $name = '';
    $info = $Model->getById($model_id);
    if ($info['extend'] != 0)
    {
        $name = $Model->getFieldById($info['extend'], 'name') . '_';
    }
    $name .= $info['name'];
    return $name;
}

/**
 * 获取属性信息并缓存
 *
 * @param integer $id
 *            属性ID
 * @param string $field
 *            要获取的字段名
 * @return string 属性信息
 *         新增配置字段功能
 */
/**
 * 获取属性信息并缓存
 *
 * @param integer $id
 *            属性ID
 * @param string $field
 *            要获取的字段名
 * @return string 属性信息
 */
function get_model_attribute ($model_id, $group = true, $fields = true)
{
    static $list;
    
    /* 非法ID */
    if (empty($model_id) || ! is_numeric($model_id))
    {
        return '';
    }
    
    /* 获取属性 */
    if (! isset($list[$model_id]))
    {
        $map = array(
                'model_id' => $model_id
        );
        $extend = M('Model')->getFieldById($model_id, 'extend');
        
        if ($extend)
        {
            $map = array(
                    'model_id' => array(
                            "in",
                            array(
                                    $model_id,
                                    $extend
                            )
                    )
            );
        }
        $info = M('Attribute')->where($map)->field($fields)->select();
        $list[$model_id] = $info;
        
        $adminCoverRemark = C('ADMIN_COVER_REMARK');
    }
    
    $attr = array();
    if ($group)
    {
        foreach ($list[$model_id] as $value)
        {
            // 先判断是否接收到cate_id，如果没有按接收到的cate_name查询
            // 判断接受的类别id所对应的备注说明是否存在，如果存在，替换备注说明
            I('get.cate_id') ? $cates = getPCates(I('get.cate_id')) : $cates = getPCates(I('get.cate_name'));
            $art_config_field = array();
            foreach ($cates as $cs)
            {
                if (! empty($cs['config_field']))
                {
                    $art_config_field = $cs['config_field'];
                    break;
                }
                else
                {
                    $art_config_field = $cs['config_field'];
                    continue;
                }
            }
            foreach (formatcon($art_config_field) as $key => $sfield)
            {
                if ($value['name'] == $sfield[0])
                {
                    $sfield[1] and $value['title'] = $sfield[1];
                    $sfield[2] and $value['remark'] = $sfield[2];
                    $value['is_show'] = $sfield[3] === '0' ? 0 : 1;
                }
            }
            $attr[$value['id']] = $value;
        }
        $sort = M('Model')->getFieldById($model_id, 'field_sort');
        
        if (empty($sort))
        { // 未排序
            $group = array(
                    1 => array_merge($attr)
            );
        }
        else
        {
            $group = json_decode($sort, true);
            
            $keys = array_keys($group);
            foreach ($group as &$value)
            {
                foreach ($value as $key => $val)
                {
                    $value[$key] = $attr[$val];
                    unset($attr[$val]);
                }
            }
            
            if (! empty($attr))
            {
                $group[$keys[0]] = array_merge($group[$keys[0]], $attr);
            }
        }
        $attr = $group;
    }
    else
    {
        foreach ($list[$model_id] as $value)
        {
            $attr[$value['name']] = $value;
        }
    }
    return $attr;
}

/**
 * 根据条件字段获取指定表的数据
 *
 * @param mixed $value
 *            条件，可用常量或者数组
 * @param string $condition
 *            条件字段
 * @param string $field
 *            需要返回的字段，不传则返回整个数据
 * @param string $table
 *            需要查询的表
 * @author huajie <banhuajie@163.com>
 */
function get_table_field ($value = null, $condition = 'id', $field = null, $table = null)
{
    if (empty($value) || empty($table))
    {
        return false;
    }
    
    // 拼接参数
    $map[$condition] = $value;
    $info = M(ucfirst($table))->where($map);
    if (empty($field))
    {
        $info = $info->field(true)->find();
    }
    else
    {
        $info = $info->getField($field);
    }
    return $info;
}

/**
 * 获取链接信息
 *
 * @param int $link_id            
 * @param string $field            
 * @return 完整的链接信息或者某一字段
 * @author huajie <banhuajie@163.com>
 */
function get_link ($link_id = null, $field = 'url')
{
    $link = '';
    if (empty($link_id))
    {
        return $link;
    }
    $link = M('Url')->getById($link_id);
    if (empty($field))
    {
        return $link;
    }
    else
    {
        return $link[$field];
    }
}

/**
 * 获取文档封面图片
 *
 * @param int $cover_id            
 * @param string $field            
 * @return 完整的数据 或者 指定的$field字段值
 * @author huajie <banhuajie@163.com>
 */
function get_cover ($cover_id, $field = null, $width = null, $height = null)
{
    if (empty($cover_id))
    {
        return false;
    }
    $picture = M('Picture')->where(array(
            'status' => 1
    ))->getById($cover_id);
    if ($field == 'path')
    {
        if (! empty($picture['url']))
        {
            $picture['path'] = $picture['url'];
        }
        else
        {
            if ($width)
            {
                $picture['path'] = get_thumb(__ROOT__ . $picture['path'], $width, $height);
            }
        }
    }
    return empty($field) ? $picture : $picture[$field];
}

/**
 * 获取文档封面图片
 *
 * @param string $src            
 * @param int $width            
 * @param int $height            
 * @return 缩略图及图片路径
 * @author hayden <hayden@yeah.net>
 */
function get_thumb ($src, $width = null, $height = null)
{
    if (empty($src))
    {
        return false;
    }
    // 缩略图
    $file = $src;
    if ($width && is_file('.' . $file))
    {
        $fileInfo = pathinfo($file);
        $fileName = $fileInfo['basename'];
        $md5dir = substr(md5($fileName), 0, 2);
        $thisThumbPath = '/Uploads/Thumb/' . $width . 'x' . $height . '/' . $md5dir . '/';
        $thumb = $thisThumbPath . $fileName;
        if (! is_file('.' . $thumb))
        {
            file_exists('.' . $thisThumbPath) or mkdir('.' . $thisThumbPath, 0777, true); // 生成新的目录给权限
            $image = new \Think\Image();
            $image->open('.' . $file);
            
            if (! $height)
            {
                
                $height = floor(($width * $image->height()) / $image->width());
            }
            
            $quality = ($width / $image->width() < 0.7) ? 80 : 98;
            
            $image->thumb($width, $height, 3)->save('.' . $thumb, null, 98);
        }
        
        $file = $thumb;
    }
    return $file;
}

/**
 * 检查$pos(推荐位的值)是否包含指定推荐位$contain
 *
 * @param number $pos
 *            推荐位的值
 * @param number $contain
 *            指定推荐位
 * @return boolean true 包含 ， false 不包含
 * @author huajie <banhuajie@163.com>
 */
function check_document_position ($pos = 0, $contain = 0)
{
    if (empty($pos) || empty($contain))
    {
        return false;
    }
    
    // 将两个参数进行按位与运算，不为0则表示$contain属于$pos
    $res = $pos & $contain;
    if ($res !== 0)
    {
        return true;
    }
    else
    {
        return false;
    }
}

/**
 * 日期处理
 */
function changedate ($date)
{
    $nian_now = date('y', time()); // 今年
    $yue_now = date('m', time()); // 本月
    $ri_now = date('d', time()); // 今天
    $nian = date('y', $date);
    $yue = date('m', $date);
    $ri = date('d', $date);
    if ($nian != $nian_now)
    {
        $rq = date('y-m-d', $date);
    }
    elseif ($nian == $nian_now)
    {
        if ($yue != $yue_now)
        {
            $rq = date('m-d', $date);
        }
        elseif ($yue == $yue_now && $ri == $ri_now)
        {
            $rq = date('今天 H:i', $date);
        }
        else
        {
            $rq = date('m-d H:i', $date);
        }
    }
    else
    {
        $rq = date('m-d', $date);
    }
    return $rq;
}

/**
 * 获取数据的所有子孙数据的id值
 *
 * @author 朱亚杰 <xcoolcc@gmail.com>
 */
function get_stemma ($pids, Model &$model, $field = 'id')
{
    $collection = array();
    
    // 非空判断
    if (empty($pids))
    {
        return $collection;
    }
    
    if (is_array($pids))
    {
        $pids = trim(implode(',', $pids), ',');
    }
    $result = $model->field($field)->where(array(
            'pid' => array(
                    'IN',
                    (string) $pids
            )
    ))->select();
    $child_ids = array_column((array) $result, 'id');
    
    while (! empty($child_ids))
    {
        $collection = array_merge($collection, $result);
        $result = $model->field($field)->where(array(
                'pid' => array(
                        'IN',
                        $child_ids
                )
        ))->select();
        $child_ids = array_column((array) $result, 'id');
    }
    return $collection;
}

/**
 * 生成guid
 *
 * @author 黄鹤 <huanghe@kcdns.com>
 */
function guid ($s)
{
    if (function_exists('com_create_guid'))
    {
        return com_create_guid();
    }
    else
    {
        mt_srand((double) microtime() * 10000);
        $charid = strtoupper(md5(uniqid(rand(), true)));
        $hyphen = chr(45);
        $uuid = substr($charid, 0, 8) . $hyphen . substr($charid, 8, 4) . $hyphen . substr($charid, 12, 4) . $hyphen . substr($charid, 16, 4) . $hyphen . substr($charid, 20, 12);
        return $uuid;
    }
}

/**
 * 处理配置文本框
 */
function formatcontent ($list)
{
    $arr = explode("\n", $list);
    $info = '';
    foreach ($arr as $val)
    {
        $val = preg_replace('/^(　|\s)*|(　|\s)*$/', '', $val);
        if ($val == '' || $info['title'] == $val)
        {
            continue;
        }
        $info .= ' <span>' . $val . '</span> ';
    }
    return $info;
}

/**
 * 处理配置文本框成数组
 */
function formatcon ($list)
{
    $arr = explode("\n", $list);
    $info = '';
    foreach ($arr as $k => $val)
    {
        $val = preg_replace('/^(　|\s)*|(　|\s)*$/', '', $val);
        $arr[$k] = explode(';', $val);
    }
    return $arr;
}

/**
 * 判断移动端
 */
function ismobile ()
{
    // 如果有HTTP_X_WAP_PROFILE则一定是移动设备
    if (isset($_SERVER['HTTP_X_WAP_PROFILE']))
        return true;
        
        // 此条摘自TPM智能切换模板引擎，适合TPM开发
    if (isset($_SERVER['HTTP_CLIENT']) && 'PhoneClient' == $_SERVER['HTTP_CLIENT'])
        return true;
        // 如果via信息含有wap则一定是移动设备,部分服务商会屏蔽该信息
    if (isset($_SERVER['HTTP_VIA']))
        // 找不到为flase,否则为true
        return stristr($_SERVER['HTTP_VIA'], 'wap') ? true : false;
        // 判断手机发送的客户端标志,兼容性有待提高
    if (isset($_SERVER['HTTP_USER_AGENT']))
    {
        $clientkeywords = array(
                'nokia',
                'sony',
                'ericsson',
                'mot',
                'samsung',
                'htc',
                'sgh',
                'lg',
                'sharp',
                'sie-',
                'philips',
                'panasonic',
                'alcatel',
                'lenovo',
                'iphone',
                'ipod',
                'blackberry',
                'meizu',
                'android',
                'netfront',
                'symbian',
                'ucweb',
                'windowsce',
                'palm',
                'operamini',
                'operamobi',
                'openwave',
                'nexusone',
                'cldc',
                'midp',
                'wap',
                'mobile'
        );
        // 从HTTP_USER_AGENT中查找手机浏览器的关键字
        if (preg_match("/(" . implode('|', $clientkeywords) . ")/i", strtolower($_SERVER['HTTP_USER_AGENT'])))
        {
            return true;
        }
    }
    // 协议法，因为有可能不准确，放到最后判断
    if (isset($_SERVER['HTTP_ACCEPT']))
    {
        // 如果只支持wml并且不支持html那一定是移动设备
        // 如果支持wml和html但是wml在html之前则是移动设备
        if ((strpos($_SERVER['HTTP_ACCEPT'], 'vnd.wap.wml') !== false) && (strpos($_SERVER['HTTP_ACCEPT'], 'text/html') === false || (strpos($_SERVER['HTTP_ACCEPT'], 'vnd.wap.wml') < strpos($_SERVER['HTTP_ACCEPT'], 'text/html'))))
        {
            return true;
        }
    }
    return false;
}

/**
 * 二维数组排序 按照指定的key 对数组进行排序
 *
 * @param array $arr
 *            将要排序的数组
 * @param string $keys
 *            指定排序的key
 * @param string $type
 *            排序类型 asc | desc
 * @return array
 * @author 申龙彪 <shenlongbiao@ucfgroup.com>
 */
function arraySort ($arr, $keys, $type = 'asc')
{
    $keysValue = $new_array = array();
    foreach ($arr as $k => $v)
    {
        $keysValue[$k] = $v[$keys];
    }
    $type == 'asc' ? asort($keysValue) : arsort($keysValue);
    reset($keysValue);
    foreach ($keysValue as $k => $v)
    {
        $new_array[$k] = $arr[$k];
    }
    return $new_array;
}

/**
 * 返回的数组进行整数映射转换
 */
function status_to_string (&$data, $map = array('status' => array(1 => '正常', -1 => '删除', 0 => '禁用', 2 => '未审核', 3 => '已拒绝')))
{
    if ($data === false || $data === null)
    {
        return $data;
    }
    $data = (array) $data;
    foreach ($data as $key => $row)
    {
        foreach ($map as $col => $pair)
        {
            if (isset($row[$col]) && isset($pair[$row[$col]]))
            {
                $data[$key][$col . '_text'] = $pair[$row[$col]];
            }
        }
    }
    return $data;
}

/**
 * 获取字典配置
 * name = city 从 dic_item 表查询
 * name = order.status 从 Service/Order/Dic 中查询
 *
 * @param string $name
 * @param string $value            
 * @param string $getAll            
 * @return multitype:
 */
function dic ($name, $value = null, $getAll = true)
{
    static $dics = [];
    if (! isset($dics[$name]))
    {
        $dics[$name] = [];
        
        // 从 service 中查询
        if (strpos($name, '.'))
        {
            list ($service, $property) = explode('.', $name);
            $service = ucfirst($service);
            $dicFile = ROOT_PATH ."Service/$service/Dic.class.php";
            $items = [];
            if(file_exists($dicFile)){
                $className = "\\Service\\{$service}\\Dic";
                $items = $className::get($property);
            }
            $dics[$name] = $items;
        }
        else
        {
            $where = [
                    'name' => $name
            ];
            $getAll or $where['status'] = 1;
            $dicData = M('dic_item')->where($where)->order('sort DESC, ID ASC')->select() ?  : [];
            foreach ($dicData as $v)
            {
                $dics[$name][$v['value']] = $v['lable'];
            }
        }
    }
    return $value === null ? $dics[$name] : $dics[$name][$value];
}

function load_static($url){
    if(is_file(($file='.'.$url))){
        return $url.'?_v='.filemtime($file);
    }else{
        return $url;
    }
}

